//
// Created by WangPeng on 2024/8/15.
//
#include "serv_sk.h"
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <iostream>

CServSocket::CServSocket(std::string ip, int port) : ip_(std::move(ip)), port_(port)
{
    struct sockaddr_in address{};

    // 1. 创建套接字
    if ((server_fd_ = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
    set_non_blocking(server_fd_);
    // 2. 设置地址和端口
    address.sin_family = AF_INET;
    address.sin_port = htons(port_);

    if (!ip_.empty())
    {
        // 将传入的IP地址转换为网络字节序并设置
        if (inet_pton(AF_INET, ip_.c_str(), &address.sin_addr) <= 0)
        {
            std::cerr << "Invalid IP address: " << ip_ << std::endl;
            close(server_fd_);
            exit(EXIT_FAILURE);
        }
    }
    else
    {
        address.sin_addr.s_addr = INADDR_ANY;
    }

    // 3. 绑定地址到套接字
    if (bind(server_fd_, (struct sockaddr*)&address, sizeof(address)) < 0)
    {
        perror("bind failed");
        close(server_fd_);
        exit(EXIT_FAILURE);
    }

    // 4. 监听连接请求
    if (listen(server_fd_, 3) < 0)
    {
        perror("listen failed");
        close(server_fd_);
        exit(EXIT_FAILURE);
    }
}

int CServSocket::set_non_blocking(int fd)
{
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1)
    {
        perror("fcntl get");
        return -1;
    }

    flags |= O_NONBLOCK;

    if (fcntl(fd, F_SETFL, flags) == -1)
    {
        perror("fcntl set");
        return -1;
    }

    return 0;
}

int CServSocket::accept_conn()
{
    struct sockaddr_in address{};
    int addr_len = sizeof(address);
    //非阻塞的接受客户端连接
    int client_socket = accept(server_fd_, (struct sockaddr*)&address, (socklen_t*)&addr_len);

    if (client_socket < 0)
    {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
        {
            return -1;
        }
        else
        {
            perror("accept failed");
            close(server_fd_);
            exit(EXIT_FAILURE);
        }
    }

    std::cout << "Connection established!" << std::endl;

    // 设置新套接字为非阻塞模式
    if (set_non_blocking(client_socket) < 0)
    {
        close(client_socket);
        return -1;
    }

    // 获取客户端的IP地址并转换为点分十进制字符串
    char client_ip[INET_ADDRSTRLEN] = {0};  // INET_ADDRSTRLEN 用于IPv4地址长度
    if (inet_ntop(AF_INET, &address.sin_addr, client_ip, INET_ADDRSTRLEN) == nullptr)
    {
        std::cerr << "Failed to convert IP address!" << std::endl;
        return -1;
    }

    std::cout << "Client connected from IP: " << client_ip << std::endl;
    client_ips_.emplace(client_socket, st_ip(address.sin_addr.s_addr, client_ip));

    return client_socket;
}

uint32_t CServSocket::get_number_ip(int fd) const
{
    auto it = client_ips_.find(fd);
    return (client_ips_.end() == it ? 0 : it->second.iip);
}

std::string CServSocket::get_string_ip(int fd) const
{
    auto it = client_ips_.find(fd);
    return (client_ips_.end() == it ? "" : it->second.sip);
}

CServSocket::~CServSocket() =  default;

